package com.gitee.fastmybatis.core.mapper;

import com.gitee.fastmybatis.core.PageInfo;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.fastmybatis.core.util.ClassUtil;
import com.gitee.fastmybatis.core.util.MapperUtil;
import com.gitee.fastmybatis.core.util.MyBeanUtil;
import org.apache.ibatis.annotations.Param;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 具备查询功能的Mapper
 * 
 * @param <E> 实体类，如：Student
 * @param <I> 主键类型，如：Long，Integer
 * @author tanghc
 */
public interface SchMapper<E, I> extends Mapper<E> {

    /**
     * 内置resultMap名称
     */
    String BASE_RESULT_MAP = "baseResultMap";

    /**
     * 根据主键查询
     * 
     * @param id
     *            主键值
     * @return 返回实体对象，没有返回null
     */
    E getById(I id);

    /**
     * 根据主键查询强制查询，忽略逻辑删除字段
     * @param id id值
     * @return 返回实体对象，没有返回null
     */
    E forceById(I id);

    /**
     * 根据条件查找单条记录
     * 
     * @param query
     *            查询条件
     * @return 返回实体对象，没有返回null
     */
    E getByQuery(@Param("query") Query query);

    /**
     * 根据字段查询一条记录
     * 
     * @param column
     *            数据库字段名
     * @param value
     *            字段值
     * @return 返回实体对象，没有返回null
     */
    E getByColumn(@Param("column") String column, @Param("value") Object value);

    /**
     * 查询总记录数
     * 
     * @param query
     *            查询条件
     * @return 返回总记录数
     */
    long getCount(@Param("query") Query query);

    /**
     * 根据字段查询结果集
     * 
     * @param column
     *            数据库字段名
     * @param value
     *            字段值
     * @return 返回实体对象集合，没有返回空集合
     */
    List<E> listByColumn(@Param("column") String column, @Param("value") Object value);

    /**
     * 查询结果集
     * 
     * @param query
     *            查询条件
     * @return 返回实体对象集合，没有返回空集合
     */
    List<E> list(@Param("query") Query query);

    /**
     * 查询指定字段结果，Map里面key对应字段名，value对应值<br>
     * 使用MyBeanUtil.mapListToObjList(listMap, Class pojoClass)方法将List&lt;Map&gt;转换成List&lt;Entity&gt;
     * @param columns
     *            返回的字段
     * @param query
     *            查询条件
     * @return 返回结果集，没有则返回空list
     * @see com.gitee.fastmybatis.core.util.MyBeanUtil#mapListToObjList(List, Class) MyBeanUtil.mapListToObjList(List, Class)
     * @see #listBySpecifiedColumns(List, Query, Class)
     */
    @Deprecated
    List<Map<String, Object>> listMap(@Param("columns") List<String> columns, @Param("query") Query query);

    /**
     * 查询返回指定的列，返回实体类集合
     * @param columns 指定字段，数据库字段名
     * @param query 查询条件
     * @return 返回实体类集合，没有则返回空list
     */
    default List<E> listBySpecifiedColumns(List<String> columns, Query query) {
        Class<E> entityClass = (Class<E>) ClassUtil.getSuperInterfaceGenricType(getClass(), 0);
        return listBySpecifiedColumns(columns, query, entityClass);
    }

    /**
     * 查询返回指定的列，返回实体类集合
     * @param columns 指定字段，数据库字段名
     * @param query 查询条件
     * @param clazz 集合元素类型，可以是对象class，也可以是基本类型class，如：UserVO.class, Integer.class, String.class。<br>
     *              当指定基本类型class时，<code>columns</code>参数只能指定一列
     * @return 返回实体类集合，没有则返回空list
     */
    default <T> List<T> listBySpecifiedColumns(List<String> columns, Query query, Class<T> clazz) {
        if (columns == null || columns.isEmpty()) {
            throw new IllegalArgumentException("未指定columns");
        }
        List<Map<String, Object>> listMap = this.listMap(columns, query);
        if (listMap == null || listMap.isEmpty()) {
            return new ArrayList<>(0);
        }
        // 如果是单值
        if (ClassUtil.isPrimitive(clazz.getSimpleName())) {
            return MyBeanUtil.mapListToValueList(listMap, clazz, columns.get(0));
        }
        return MyBeanUtil.mapListToObjList(listMap, clazz);
    }

    /**
     * 分页查询
     * @param query 查询条件
     * @return 返回分页信息
     */
    default PageInfo<E> page(Query query) {
        return MapperUtil.query(this, query);
    }

}
